
local bars = CreateFrame("Frame", nil, UIParent)

bars:SetScript("OnEvent", function (self, event, ...)
	local handler = self[event]
	if handler then handler(self, event, ...) end
end)

function bars:ADDON_LOADED(addon)
	if addon == "Bars" then
		self.db = BarsDB

		self.ADDON_LOADED = nil
		self:UnregisterEvent"ADDON_LOADED"
	end
end
bars:RegisterEvent"ADDON_LOADED"

local function Button_Set(self, type, ...)
	if type == "item" then
		local itemid, count = ...
		self:SetAttribute("type", "item")
		self:SetAttribute("item", "item:"..itemid)
		local stacksize,_,texture = select(8, GetItemInfo(itemid))
		self.icon:SetTexture(texture)
		if (not stacksize or stacksize == 1) and (not count or count <= 1) then
			self.count:Hide
		else
			self.count:SetText(count)
			self.count:Show()
		end
		CooldownFrame_SetTimer(frame.cooldown, GetItemCooldown(itemid))
	elseif type == "spell" then
		local spell = ...
		self:SetAttribute("type", "spell")
		self:SetAttribute("spell", spell)
		local texture = select(2, GetSpellInfo(spell))
		self.icon:SetTexture(texture)
		self.count:Hide
	else
		self.icon:SetTexture()
		self:SetAttribute("type", "")
	end
end

local function MakeActionButton(parent, inherit)
	local child

	local button = CreateFrame("CheckButton", nil, parent, inherit)
	button:SetAttribute("*unit2", "player")

	button:SetSize(36, 36)

	child = button:CreateTexture(nil, "BACKGROUND")
	child:SetAllPoints()
	button.icon = child

--~ 	child = button:CreateTexture(nil, "ARTWORK")
--~ 	child:SetTexture"Interface\\Buttons\\UI-QuickslotRed"
--~ 	child:SetAllPoints()
--~ 	button.flash = child

--~ 	child = button:CreateFontString(nil, "ARTWORK")
--~ 	child:SetFontObject(NumberFontNormalSmallGray)
--~ 	child:SetJustifyH"RIGHT"
--~ 	child:SetSize(36, 10)
--~ 	child:SetPoint("TOPLEFT", -2, -2)
--~ 	button.hotkey = child
--~ 	child:Hide()

	child = button:CreateFontString(nil, "ARTWORK")
	child:SetFontObject(NumberFontNormal)
	child:SetJustifyH"RIGHT"
	child:SetPoint("BOTTOMRIGHT", -2, 2)
	button.count = child

--~ 	child = button:CreateFontString(nil, "OVERLAY")
--~ 	child:SetFontObject(GameFontHighlightSmallOutline)
--~ 	child:SetSize(36, 10)
--~ 	child:SetPoint("BOTTOM", 0, 2)
--~ 	button.name = child

--~ 	child = button:CreateTexture(nil, "OVERLAY")
--~ 	child:SetTexture"Interface\\Buttons\\UI-ActionButton-Border"
--~ 	child:SetBlendMode"ADD"
--~ 	child:SetSize(62, 62)
--~ 	child:SetPoint"CENTER"
--~ 	button.border = child
--~ 	child:Hide()

	child = CreateFrame("Cooldown", nil, button)
	child:SetSize(36, 36)
	child:SetPoint("CENTER", 0, -1)
	button.cooldown = child

	child = button:CreateTexture()
	child:SetTexture"Interface\\Buttons\\UI-Quickslot2"
	child:SetSize(66, 66)
	child:SetPoint("CENTER", 0, -1)
	button:SetNormalTexture(child)

	child = button:CreateTexture()
	child:SetTexture"Interface\\Buttons\\UI-Quickslot-Depress"
	child:SetAllPoints()
	button:SetPushedTexture(child)

	child = button:CreateTexture()
	child:SetTexture"Interface\\Buttons\\ButtonHilight-Square"
	child:SetBlendMode"ADD"
	child:SetAllPoints()
	button:SetHighlightTexture(child)

	child = button:CreateTexture()
	child:SetTexture"Interface\\Buttons\\CheckButtonHilight"
	child:SetBlendMode"ADD"
	child:SetAllPoints()
	button:SetCheckedTexture(child)

	button.Set = Button_Set

	return button
end

local function Button_AddSecondChild(self)
	local child = MakeActionButton(parent,
		"SecureHandlerBaseTemplate, SecureActionButtonTemplate")

	parent:SetFrameRef("child", child)
	parent:Execute[[children[#children + 1] = self:GetFrameRef"child"]]
	self.children[#self.children + 1] = child

	if self.group then
		self.group:AddButton(child, {
			Icon = child.icon,
			Border = child.border,
			Flash = child.flash,
			Cooldown = child.cooldown,
			AutoCast = child.autocast,
			AutoCastable = child.autocastable,
			HotKey = child.hotkey,
			Count = child.count,
			Name = child.name,
		})
	end

	return child
end

local function Button_AddFirstChild(self)
	local child = MakeActionButton(parent,
		"SecureHandlerEnterLeaveTemplate, SecureActionButtonTemplate")

	child:Execute[[children = newtable()]]
	child:SetAttribute("_onenter", [[
		self:SetAutoHide(.5)
		for i = 1, count do
			self:AddToHide(children[i])
		end
	]])

	self.firstChild = child
	self:SetFrameRef("child", child)
	self:Execute[[child = self:GetFrameRef"child"]]

	self.children = {child}
	self.AddChild = Button_AddSecondChild

	if self.group then
		self.group:AddButton(child, {
			Icon = child.icon,
			Border = child.border,
			Flash = child.flash,
			Cooldown = child.cooldown,
			AutoCast = child.autocast,
			AutoCastable = child.autocastable,
			HotKey = child.hotkey,
			Count = child.count,
			Name = child.name,
		})
	end

	return child
end

local function Button_GetChild(self, index)
	-- this method assume that it will be called for each index in a linear way
	return self.children[index] or self:AddChild()
end

local function MakeBaseActionButton(parent, index)
	local child = MakeActionButton(parent,
		"SecureHandlerEnterLeaveTemplate, SecureActionButtonTemplate")
	child:SetAttribute("_onenter", [[if child then child:Show() end]])

	child.AddChild = Button_AddFirstChild
	child.GetChild = Button_GetChild

	local BF = LibStub("LibButtonFacade-1.0", true)
	if BF then
		child.group = BF:CreateGroup("Bars", "Bar"..index)
	end

	return child
end

local function fill_table(set, items)
	for item in pairs(set) do
		item = tonumber(item)
		local count = item and GetItemCount(item) or 0
		if count > 0 then
			items[#items + 1] = item
		end
	end
end

local function Button_UpdatePT(self)
	local set = self.ptSet
	local _, first = next(set)
	local items = {}, counts = {}
	if type(first) == "table" then
		for _,t in ipairs(set) do
			fill_table(t, items)
		end
	else
		fill_table(set, items)
	end
	if #items == 0 then
		self:Hide()
	elseif #items == 1 then
		self:SetAttribute("_onenter", nil)
	else
		self:SetAttribute("_onenter", [[if child then child:Show() end]])
		self.firstChild:Execute(string.format("count = %d", #items - 1))
	end
	for i, item in ipairs(items) do
		local child = self:GetChild(i)
		child:Set("item", items[i])
		child:Show()
	end
	for i = #items + 1, #self.children do
		self.children[i]:Hide()
	end
end

function bars:PLAYER_LOGIN()
	local PT = LibStub"LibPeriodicTable-3.1"
	PT:AddData("PT3BarCustom", self.db.PT)
	self.buttons = {}
	for index, data in ipairs(self.db.buttons) do
		local button = MakeBaseActionButton(self, index)
		self.buttons[index] = button
		local set = PT(data)
		if set then
			button.Update = Button_UpdatePT
			button.ptSet = set
			button:Update()
		end
	end
	self.PLAYER_LOGIN = nil
	self:UnregisterEvent"PLAYER_LOGIN"
end
bars:RegisterEvent"PLAYER_LOGIN"
